package com.techsoft.plugins;

import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PluginJarUtils {
	private static final Logger Log = LoggerFactory
			.getLogger(PluginJarUtils.class);

	public static File[] findJarsForArray(File jarFileDir) {
		if (jarFileDir.isDirectory()) {
			return jarFileDir.listFiles(new FileFilter() {

				@Override
				public boolean accept(File pathname) {
					return pathname.getName().endsWith(".jar");
				}
			});
		} else {
			return null;
		}
	}

	public static List<File> findJarsForList(File jarFileDir) {
		List<File> result = new ArrayList<File>();
		File[] list = findJarsForArray(jarFileDir);
		Collections.addAll(result, list);

		return result;
	}

	public static Set<File> findJarsForSet(File jarFileDir) {
		Set<File> result = new HashSet<File>();
		File[] list = findJarsForArray(jarFileDir);
		Collections.addAll(result, list);

		return result;
	}

	public static String getRealPluginName(File jarFile) {
		String pluginName = jarFile.getName();
		pluginName = pluginName.substring(0, pluginName.lastIndexOf("."));
		pluginName = pluginName + String.valueOf(jarFile.lastModified());

		return pluginName;
	}

	public static Map<String, String> findJarsForMap(File jarFileDir) {
		Map<String, String> result = new HashMap<String, String>();
		File[] list = findJarsForArray(jarFileDir);
		for (File file : list) {
			String pluginName = getRealPluginName(file);
			result.put(pluginName, file.getAbsolutePath());
		}

		return result;
	}

	public static File unzip(File file, String outputPath,
			boolean unzipToSameNameDir) {
		if (file.isFile()) {
			String newOutputPath = null;
			if (unzipToSameNameDir) {
				String filename = getRealPluginName(file);
				newOutputPath = outputPath.concat(File.separator).concat(
						filename);
			} else {
				newOutputPath = outputPath;
			}
			File outputDir = new File(newOutputPath);
			if (!outputDir.exists()) {
				outputDir.mkdirs();
			}

			try {
				ZipFile zipfile = new ZipFile(file);
				try {
					Enumeration<? extends ZipEntry> zipEntrys = zipfile
							.entries();
					byte[] buf = new byte[2048];
					while (zipEntrys.hasMoreElements()) {
						ZipEntry zipEntry = zipEntrys.nextElement();
						if (zipEntry.isDirectory()) {
							new File(newOutputPath + File.separator
									+ zipEntry.getName()).mkdirs();
							continue;
						}

						InputStream in = zipfile.getInputStream(zipEntry);
						try {
							File entryFile = new File(newOutputPath
									+ File.separator + zipEntry.getName());
							File parentFile = entryFile.getParentFile();
							if ((parentFile != null) && !parentFile.exists()) {
								parentFile.mkdirs();
							}

							FileOutputStream out = new FileOutputStream(
									entryFile);
							try {
								IOUtils.copy(in, out, buf);
							} finally {
								out.flush();
								out.close();
							}
						} finally {
							in.close();
						}

					}
				} finally {
					zipfile.close();
					zipfile = null;
				}
			} catch (ZipException e) {
				Log.error(file.getAbsolutePath()
						+ "  is not a valid compressed file");
				Log.error(e.getMessage(), e);
			} catch (IOException e) {
				Log.error(e.getMessage(), e);
			}

			return outputDir;
		} else {
			return null;
		}
	}
}
